/*
 * Created by SharpDevelop.
 * User: Tivadar Papai
 * Date: 8/23/2007
 * Time: 6:42 AM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Collections.Generic;
using RoverStudio.Math;

namespace RoverStudio.Common.WorldModel
{
	public class WorldChangedEventArgs:EventArgs
	{
		public List<PhysicalObject> physicalObjects;
		public List<CreatedObject> createdObjects;
		public DateTime lastChangeDate;
		public WorldModelObject lastChangedObject;
		
		public WorldChangedEventArgs(
			List<PhysicalObject> physicalObjects,
			List<CreatedObject> createdObjects,
			DateTime lastChangeDate,
			WorldModelObject lastChangedObject)
		{
			this.physicalObjects = physicalObjects;
			this.createdObjects = createdObjects;
			this.lastChangeDate = lastChangeDate;
			this.lastChangedObject = lastChangedObject;
		}
	}
	
	public delegate void WorldChangedEventHandler(object sender, WorldChangedEventArgs wce);
	
	/// <summary>
	/// The model of the physical world.
	/// </summary>
	public class WorldModel
	{
		private Vector3D origin = new Vector3D(0.0,0.0,0.0);
		
		public Vector3D Origin
		{
			get { return origin; }
			set { origin = value; }
		}
		
		public event WorldChangedEventHandler WorldChanged;
		
		private List<PhysicalObject> physicalObjects = new List<PhysicalObject>();
		private List<CreatedObject> createdObjects = new List<CreatedObject>();
		
		public WorldModel()
		{
		}

		public void ObjectsChanged(object sender, WorldModelObjectEventArgs wmea)
		{
			if (WorldChanged!=null)
				WorldChanged(this, 
				             new WorldChangedEventArgs(
				             	this.physicalObjects,
				             	this.createdObjects,
				             	wmea.time,
				             	wmea.worldModelObject));
		}
		
		public void AddWorldModelObject(WorldModelObject wmo)
		{
			if (wmo is PhysicalObject)
				this.physicalObjects.Add((PhysicalObject)wmo);
			if (wmo is CreatedObject)
				this.createdObjects.Add((CreatedObject)wmo);
			
			wmo.ObjectChanged+=new ObjectChangedHandle(ObjectsChanged);
		}
		
		public void RemoveWorldModelObject(WorldModelObject wmo)
		{
			if (wmo is PhysicalObject)
				this.physicalObjects.Remove((PhysicalObject)wmo);
			if (wmo is CreatedObject)
				this.createdObjects.Remove((CreatedObject)wmo);
			
			wmo.ObjectChanged-=new ObjectChangedHandle(ObjectsChanged);
		}
		
		public List<PhysicalObject> GetPhysicalObjects()
		{
			return this.physicalObjects;
		}

		public List<CreatedObject> GetCreatedObjects()
		{
			return this.createdObjects;
		}

	
		public List<PhysicalObject> GetPhysicalObjects(Vector3D position, Vector2D direction)
		{
            throw new NotImplementedException();
            //TODO: return all the physical objects "intersected" by the position + t*direction line
			return null;
		}

		public List<CreatedObject> GetCreatedObjects(Vector3D position, Vector2D direction)
		{
            throw new NotImplementedException();
            //TODO: return all the created objects "intersected" by the position + t*direction line
            return null;
		}


        public WorldModelObject FindObject(string name)
        {
            PhysicalObject po = physicalObjects.Find(delegate(PhysicalObject o)
            {
                return o.Name == name;
            });
            if (po != null)
                return po;
            CreatedObject co = createdObjects.Find(delegate(CreatedObject o)
            {
                return o.Name == name;
            });
            return co;
        }
    }
}
